package botlab.engine.physics;

import com.jme3.collision.CollisionResults;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import java.util.ArrayList;
import java.util.Arrays;

/**
 *
 * @author Quentin
 */
public class RayCast
{
    private float dist;
    private int nbHits;
    private Vector3f hit;
    private String name;
    private Node shootables;
    private boolean hasHit=false;
    
    private ArrayList<Node> nodesToAvoid;
    
    /**
     *
     * @param node Node containing spatial to be detected (including toAvoid)
     * @param toAvoid Array of Node that don't have to be detected
     */
    public RayCast(Node node, Node[] toAvoid)
    {
        this.shootables=node;
        this.nodesToAvoid= new ArrayList<Node>();
        nodesToAvoid.addAll(Arrays.asList(toAvoid));
        cleanResults();
    }
    /**
     *
     * @param origin Start point of the ray
     * @param direction Direction of the ray
     * @param shootables spatials to be detected
     */
    public void rayCastFromPoint(Vector3f origin ,Vector3f direction, Node shootables)
    {
        cleanResults();
        int i; boolean stop=false;
        Ray ray = new Ray(origin, direction);
        CollisionResults results = new CollisionResults();
        shootables.collideWith(ray, results);
        
        if (results.size() > 0)
        {
            
            nbHits=results.size();
            // We withdraw Nodes that we don't want to detect
            for(i=0;i<nbHits && stop==false;i++)
            {
                if(!nodesToAvoid.contains(results.getCollision(i).getGeometry().getParent()))
                    stop=true;
                nbHits--;
            }
            // If, after that, it remains results, we have detected a Node.
            if(nbHits!=0)
            {
                hasHit=true;
                dist = results.getCollision(i).getDistance();
                hit = results.getCollision(i).getContactPoint();
                name = results.getCollision(i).getGeometry().getName();
            }
            
        }
    }
    
    /*
     * Reset detections results.
     */
    private void cleanResults()
    {
        dist=9999;
        nbHits=0;
        name="";
        hasHit=false;
    }
    
    /**
     *
     * @param origin Starting point of the ray
     * @param direction Direction of the ray
     */
    public void rayCastFromPoint(Vector3f origin, Vector3f direction)
    {
        this.rayCastFromPoint(origin, direction, this.shootables);
    }
    
    public float getDistance()
    {
        return dist;
    }
    public int getNbHits()
    {
        return nbHits;
    }
    public Vector3f getHitPoint()
    {
        return hit;
    }
    public String getName()
    {
        return name;
    }
    public boolean isColliding()
    {
        return hasHit;
    }
}
